#include "../display.h"
#include <nxos.h>

NX_Solt fb_dev = NX_SOLT_INVALID_VALUE;

NX_Error WM_DisplayFrameBufferInit(void)
{
    NX_Error err;

    /* open device */
    fb_dev = NX_DeviceOpen("fb0", 0);
    if (fb_dev == NX_SOLT_INVALID_VALUE)
    {
        NX_Printf("display: open video device failed!\n");
        return NX_ENORES;
    }

    NX_FramebufferInfo fbi;

    if (NX_DeviceControl(fb_dev, NX_FRAMEBUFFER_CMD_GETINFO, &fbi) != NX_EOK)
    {
        NX_Printf("display: get video info failed!\n");
        err = NX_EPERM;
        goto close_fb_dev;
    }

    NX_Printf("display: fbinfo: bpp:%d, scanline:%d, x:%d, y:%d, base:%p\n",
        fbi.bitsPerPixel, fbi.bytesPerScanLine, fbi.xResolution, fbi.yResolution, fbi.phyBasePtr);

    int bytes_per_pixel = fbi.bitsPerPixel / 8;
    NX_Size fb_len = bytes_per_pixel * fbi.yResolution * fbi.xResolution; 
    void *fb_buf = NX_DeviceMap(fb_dev, fb_len, NX_PROT_READ | NX_PROT_WRITE);
    if (fb_buf == NX_NULL) {
        NX_Printf("display: map video buffer failed!\n");
        err = NX_EPERM;
        goto close_fb_dev;
    }

    NX_SurfaceWrap(WM_DisplayGetSurface(), (NX_Color *)fb_buf, fbi.xResolution, fbi.yResolution);
    
    WM_DisplaySetPhyBase(fbi.phyBasePtr);

    return NX_EOK;

close_fb_dev:
    NX_DeviceClose(fb_dev);
    return err;
}

NX_Error WM_DisplayFrameBufferExit(void)
{
    NX_DeviceClose(fb_dev);
    return NX_EOK;
}

NX_Error WM_DisplayFrameBufferPresent(void)
{
    NX_DeviceControl(fb_dev, NX_FRAMEBUFFER_CMD_PRESENT, NX_NULL);
    return NX_EOK;
}
